package service

import (
	"context"
	auth2 "fly/core/auth"
	"fly/global"
	"fly/models"
	"fly/schema"
	"fmt"
	"github.com/beego/beego/v2/client/orm"
	"github.com/duke-git/lancet/v2/slice"
	"github.com/pkg/errors"
	"net/url"
)

const (
	SysUserCacheSimple     = "SysUserCacheSimple:%d"
	SysUserCacheRealName   = "SysUserCacheRealName:%d"
	SysUserCacheIsSuperMan = "SysUserCacheIsSuperman:%d"
)

type SysUserService struct {
	BaseService
}

// GetPaginateData 分页获取
func (c *SysUserService) GetPaginateData(params url.Values) ([]*models.SysUser, Pagination) {
	//搜索、查询字段赋值
	c.WhereField = append(c.WhereField, new(models.SysUser).WhereField()...)

	var users []*models.SysUser
	o := orm.NewOrm().QueryTable(new(models.SysUser))
	_, err := c.PaginateAndScopeWhere(o, params).All(&users)
	if err != nil {
		return nil, c.Pagination
	}
	return users, c.Pagination
}

// GetDeptUserIds 根据部门下用户ids
func (c *SysUserService) GetDeptUserIds(deptId int64) []int64 {
	var list []*models.SysUser
	qs := orm.NewOrm().QueryTable(new(models.SysUser)).Filter("dept_id", deptId).Filter("status__gte", schema.Enabled)
	_, err := qs.All(&list, "id")
	if err != nil {
		return nil
	}
	ids := slice.Map(list, func(index int, item *models.SysUser) int64 {
		return item.Id
	})
	return ids
}

func (c *SysUserService) GetUserById(userId int64) (*models.SysUser, error) {
	key := fmt.Sprintf(SysUserCacheSimple, userId)
	return global.GetCache[*models.SysUser](key, func() (*models.SysUser, error) {
		user := models.SysUser{}
		err := orm.NewOrm().QueryTable(new(models.SysUser)).Filter("id", userId).One(&user)
		return &user, err
	})
}

func (c *SysUserService) GetUserRealNameById(userId int64) (string, error) {
	key := fmt.Sprintf(SysUserCacheRealName, userId)
	return global.GetCache[string](key, func() (string, error) {
		user := &models.SysUser{}
		err := orm.NewOrm().QueryTable(new(models.SysUser)).Filter("id", userId).One(user, "real_name")
		return user.RealName, err
	})
}

// IsSuperAdminUser 是否是超级管理员用户
func (c *SysUserService) IsSuperAdminUser(userId int64) bool {
	key := fmt.Sprintf(SysUserCacheIsSuperMan, userId)
	ok, _ := global.GetCache[bool](key, func() (bool, error) {
		user := &models.SysUser{}
		if err := orm.NewOrm().QueryTable(new(models.SysUser)).Filter("id", userId).One(user, "super_admin"); err != nil {
			return false, nil
		}
		return user.IsSuperAdmin(), nil
	})
	return ok
}

func (c *SysUserService) GenerateToken(ctx context.Context, userID string) (*auth2.TokenInfo, error) {
	tokenInfo, err := global.JwtAuth.GenerateToken(ctx, userID)
	if err != nil {
		return nil, errors.WithStack(err)
	}
	return &tokenInfo, nil
}

func (c *SysUserService) RefreshToken(ctx context.Context, token string) (*auth2.TokenInfo, error) {
	tokenInfo, err := global.JwtAuth.RefreshToken(ctx, token)
	if err != nil {
		return nil, errors.WithStack(err)
	}
	return &tokenInfo, nil
}

func (c *SysUserService) DestroyToken(ctx context.Context, token string) error {
	err := global.JwtAuth.DestroyToken(ctx, token)
	if err != nil {
		return errors.WithStack(err)
	}
	return nil
}
